﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IRProject.Model
{
    class BoolenQueryHandler
    {
        enum Operation
        {
            And,
            Or
        }

        String OriginalQuery;
        List<String> _termList = new List<string>();
        List<Operation> _opList = new List<Operation>();
        Model _model;
        List<Node> _leafNode = new List<Node>();
        Node tree;

        public BoolenQueryHandler(Model model)
        {
            this._model = model;
        }

        public List<ResultData> GetResultList(String query) 
        {
            OriginalQuery = query;
            recursiveMethod(query);//set好 _termList 跟_opList
            constructTree(); //建tree

            return calculateResult();
        }

        String recursiveMethod(String query) //(apple&&book)||dog  >>  -apple&&book-||dog  (apple&&book)||(dog&&cat)  >> -apple&&book-||-dog&&cat-
        {
            String ans = "";
            if (query.Contains("("))
            {
                int leftpos = query.LastIndexOf('(');
                query = query.Remove(leftpos, 1);
                query = query.Insert(leftpos, "-");
                leftpos++;
                int rightpos = query.Substring(leftpos).IndexOf(')') + leftpos;
                query = query.Remove(rightpos, 1);
                query = query.Insert(rightpos, "-");

                String subquery = query.Substring(leftpos, rightpos - leftpos);
                if (subquery.Contains("&&"))
                {
                    String[] temp = subquery.Split('&');
                    _termList.Add(temp[0]);
                    _termList.Add(temp[2]);
                    _opList.Add(Operation.And);
                }
                else if (subquery.Contains("||"))
                {
                    String[] temp = subquery.Split('|');
                    _termList.Add(temp[0]);
                    _termList.Add(temp[2]);
                    _opList.Add(Operation.Or);
                }
                else
                {
                }

                Guid g = Guid.NewGuid();
                query = query.Replace(subquery, "--" + g);

                ans = recursiveMethod(query);
            }
            else
            {
                if (query.Contains("&&"))
                {
                    String[] temp = query.Split('&');
                    if (temp[0].Contains("&&") || temp[0].Contains("||"))
                    {
                        ans = recursiveMethod(temp[0]);
                    }
                    else
                    {
                        _termList.Add(temp[0]);
                    }
                    if (temp[2].Contains("&&") || temp[2].Contains("||")) 
                    {
                        ans = recursiveMethod(temp[2]);
                    }
                    else
                    {
                        _termList.Add(temp[2]);
                    }
                    _opList.Add(Operation.And);
                }
                else if (query.Contains("||"))
                {
                    String[] temp = query.Split('|');
                    if (temp[0].Contains("&&") || temp[0].Contains("||"))
                    {
                        ans = recursiveMethod(temp[0]);
                    }
                    else
                    {
                        _termList.Add(temp[0]);
                    }
                    if (temp[2].Contains("&&") || temp[2].Contains("||"))
                    {
                        ans = recursiveMethod(temp[2]);
                    }
                    else
                    {
                        _termList.Add(temp[2]);
                    }
                    _opList.Add(Operation.Or);
                }
                ans = query;
            }
            return ans;
        }

        
        Dictionary<int, Node> nodeList = new Dictionary<int, Node>(); 

        void constructTree()
        {
            int opi = 0;
            Node node = new AndNode();
            while(_termList.Count > 1) 
            {
                switch(_opList[opi])
                {
                    case Operation.And:
                        node = new AndNode();
                        break;
                    case Operation.Or:
                        node = new OrNode();
                        break;
                }
                opi++;
                String temp = _termList[0];
                String temp1 = _termList[1];
                Node leafNode;

                if (temp1.Contains("-"))
                {
                    if (opi - 2 >= 0) node.Add(nodeList[opi - 2]);
                    else node.Add(tree);
                }
                else
                {
                    leafNode = new LeafNode(_model, temp1);
                    node.Add(leafNode);
                    _leafNode.Add(leafNode);
                }

                if (temp.Contains("-")) 
                {
                    if (opi - 3>=0) node.Add(nodeList[opi - 3]);
                    else node.Add(tree);
                }
                else
                {
                    leafNode = new LeafNode(_model, temp);
                    node.Add(leafNode);
                    _leafNode.Add(leafNode);
                }
                
                
                tree = node;
                nodeList.Add(opi-1, node);
                _termList.Remove(temp);
                _termList.Remove(temp1);
            }
            if (_termList.Count == 1) 
            {
                switch (_opList[opi])
                {
                    case Operation.And:
                        node = new AndNode();
                        break;
                    case Operation.Or:
                        node = new OrNode();
                        break;
                }
                opi++;
                String temp = _termList[0];

                node.Add(tree);

                Node leafNode;
                if (temp.Contains("-"))
                {
                    if (opi - 3 >= 0) node.Add(nodeList[0]);
                    else node.Add(tree);
                }
                else
                {
                    leafNode = new LeafNode(_model, temp);
                    node.Add(leafNode);
                    _leafNode.Add(leafNode);
                }

                
                
                tree = node;
                nodeList.Add(opi - 1, node);
                _termList.Remove(temp);
            }

            if (_opList.Count == 0) 
            {
                tree = new LeafNode(_model, OriginalQuery);
                _leafNode.Add(tree);
            }
        }

        List<ResultData> calculateResult()
        {
            foreach (LeafNode node in _leafNode) 
            {
                node.Calculate(_model.Documents);
            }
            return tree.GetResult();
        }
    }

    

    //public Model()
    //    {
    //       //_tfidf= InitializeFtidfAlgorithm();

    //        string[] docs=new string[]{"asd","du","you are gay","fuck you"};
    //        Node root = new AndNode();
    //        LeafNode apple = new LeafNode(this);
    //        LeafNode dog = new LeafNode(this);
    //        apple.Calculate("apple", docs);
    //        dog.Calculate("dog", docs);

    //        root.Add(apple);
    //        root.Add(dog);

    //        //boolen result
    //        List<ResultData> results = root.GetResult();

    //    }

}
